package com.atguigu.juc.atomics;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * @author yanglin
 * @create 2024-01-26 16:17 星期五
 * description:
 */
public class AtomicReferenceFieldUpdaterDemo {

    /**
     * 需求
     *  多线程并发调用一个类的初始化方法，如果未被初始化过，执行初始化工作
     *  要求：只能被初始化一次，只能又一个线程成功
     */

    public static void main(String[] args) throws InterruptedException {
        MyVar myVar = new MyVar();
        CountDownLatch countDownLatch = new CountDownLatch(10);

        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    myVar.init(myVar);
                }finally {
                    countDownLatch.countDown();
                }
            }).start();
        }
        
        countDownLatch.await();
    }
    
}


class MyVar {
    
    public volatile Boolean isInit = Boolean.FALSE;
    
    AtomicReferenceFieldUpdater<MyVar,Boolean> referenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(MyVar.class,Boolean.class,"isInit");
    
    public void init(MyVar myVar){
        if (referenceFieldUpdater.compareAndSet(myVar,Boolean.FALSE,Boolean.TRUE)) {
            System.out.println(Thread.currentThread().getName() + "\t   ---start init,need 3 seconds");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "\t ---- over init");
        }else {
            System.out.println(Thread.currentThread().getName() + "\t The thread has already been initialized!");
        }
    }
}
